<?php

include_once("plog-functions.php");

/*

Zip file creation class
makes zip files on the fly...

use the functions add_dir() and add_file() to build the zip file;
see example code below

by Eric Mueller
http://www.themepark.com

v1.1 9-20-01
  - added comments to example

v1.0 2-5-01

initial version with:
  - class appearance
  - add_file() and file() methods
  - gzcompress() output hacking
by Denis O.Philippov, webmaster@atlant.ru, http://www.atlant.ru

*/

// official ZIP file format: http://www. // pkware.com/appnote.txt

class zipfile  
{  

    var $datasec = array(); // array to store compressed data
    var $ctrl_dir = array(); // central directory   
    var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00"; //end of Central directory record
    var $old_offset = 0;

    function add_dir($name)   

    // adds "directory" to archive - do this before putting any files in directory!
    // $name - name of directory... like this: "path/"
    // ...then you can add files using add_file with names like "path/file.txt"
    {  
        $name = str_replace("\\", "/", $name);  

        $fr = "\x50\x4b\x03\x04";
        $fr .= "\x0a\x00";    // ver needed to extract
        $fr .= "\x00\x00";    // gen purpose bit flag
        $fr .= "\x00\x00";    // compression method
        $fr .= "\x00\x00\x00\x00"; // last mod time and date

        $fr .= pack("V",0); // crc32
        $fr .= pack("V",0); //compressed filesize
        $fr .= pack("V",0); //uncompressed filesize
        $fr .= pack("v", strlen($name) ); //length of pathname
        $fr .= pack("v", 0 ); //extra field length
        $fr .= $name;  
        // end of "local file header" segment

        // no "file data" segment for path

        // "data descriptor" segment (optional but necessary if archive is not served as file)
        $fr .= pack("V",$crc); //crc32
        $fr .= pack("V",$c_len); //compressed filesize
        $fr .= pack("V",$unc_len); //uncompressed filesize

        // add this entry to array
        $this -> datasec[] = $fr;

        $new_offset = $this->old_offset + strlen ($fr) ;
        //$new_offset = strlen(implode("", $this->datasec));

        // ext. file attributes mirrors MS-DOS directory attr byte, detailed
        // at http://support.microsoft.com/support/kb/articles/Q125/0/19.asp

        // now add to central record
        $cdrec = "\x50\x4b\x01\x02";
        $cdrec .="\x00\x00";    // version made by
        $cdrec .="\x0a\x00";    // version needed to extract
        $cdrec .="\x00\x00";    // gen purpose bit flag
        $cdrec .="\x00\x00";    // compression method
        $cdrec .="\x00\x00\x00\x00"; // last mod time & date
        $cdrec .= pack("V",0); // crc32
        $cdrec .= pack("V",0); //compressed filesize
        $cdrec .= pack("V",0); //uncompressed filesize
        $cdrec .= pack("v", strlen($name) ); //length of filename
        $cdrec .= pack("v", 0 ); //extra field length   
        $cdrec .= pack("v", 0 ); //file comment length
        $cdrec .= pack("v", 0 ); //disk number start
        $cdrec .= pack("v", 0 ); //internal file attributes
        $ext = "\x00\x00\x10\x00";
        $ext = "\xff\xff\xff\xff";  
        $cdrec .= pack("V", 16 ); //external file attributes  - 'directory' bit set

        $cdrec .= pack("V", $this -> old_offset ); //relative offset of local header
        $this -> old_offset = $new_offset;

        $cdrec .= $name;  
        // optional extra field, file comment goes here
        // save to array
        $this -> ctrl_dir[] = $cdrec;  

         
    }


    function add_file($data, $name)   

    // adds "file" to archive   
    // $data - file contents
    // $name - name of file in archive. Add path if your want

    {  
        $name = str_replace("\\", "/", $name);  
        //$name = str_replace("\\", "\\\\", $name);

        $fr = "\x50\x4b\x03\x04";
        $fr .= "\x14\x00";    // ver needed to extract
        $fr .= "\x00\x00";    // gen purpose bit flag
        $fr .= "\x08\x00";    // compression method
        $fr .= "\x00\x00\x00\x00"; // last mod time and date

        $unc_len = strlen($data);  
        $crc = crc32($data);  
        $zdata = gzcompress($data);  
        $zdata = substr( substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
        $c_len = strlen($zdata);  
        $fr .= pack("V",$crc); // crc32
        $fr .= pack("V",$c_len); //compressed filesize
        $fr .= pack("V",$unc_len); //uncompressed filesize
        $fr .= pack("v", strlen($name) ); //length of filename
        $fr .= pack("v", 0 ); //extra field length
        $fr .= $name;  
        // end of "local file header" segment
         
        // "file data" segment
        $fr .= $zdata;  

        // "data descriptor" segment (optional but necessary if archive is not served as file)
        $fr .= pack("V",$crc); //crc32
        $fr .= pack("V",$c_len); //compressed filesize
        $fr .= pack("V",$unc_len); //uncompressed filesize

        // add this entry to array
        $this -> datasec[] = $fr;

        $new_offset = strlen(implode("", $this->datasec));

        // now add to central directory record
        $cdrec = "\x50\x4b\x01\x02";
        $cdrec .="\x00\x00";    // version made by
        $cdrec .="\x14\x00";    // version needed to extract
        $cdrec .="\x00\x00";    // gen purpose bit flag
        $cdrec .="\x08\x00";    // compression method
        $cdrec .="\x00\x00\x00\x00"; // last mod time & date
        $cdrec .= pack("V",$crc); // crc32
        $cdrec .= pack("V",$c_len); //compressed filesize
        $cdrec .= pack("V",$unc_len); //uncompressed filesize
        $cdrec .= pack("v", strlen($name) ); //length of filename
        $cdrec .= pack("v", 0 ); //extra field length   
        $cdrec .= pack("v", 0 ); //file comment length
        $cdrec .= pack("v", 0 ); //disk number start
        $cdrec .= pack("v", 0 ); //internal file attributes
        $cdrec .= pack("V", 32 ); //external file attributes - 'archive' bit set

        $cdrec .= pack("V", $this -> old_offset ); //relative offset of local header
//      &n // bsp; echo "old offset is ".$this->old_offset.", new offset is $new_offset<br>";
        $this -> old_offset = $new_offset;

        $cdrec .= $name;  
        // optional extra field, file comment goes here
        // save to central directory
        $this -> ctrl_dir[] = $cdrec;  
    }

    function file() { // dump out file   
        $data = implode("", $this -> datasec);  
        $ctrldir = implode("", $this -> ctrl_dir);  

        return   
            $data.  
            $ctrldir.  
            $this -> eof_ctrl_dir.  
            pack("v", sizeof($this -> ctrl_dir)).     // total # of entries "on this disk"
            pack("v", sizeof($this -> ctrl_dir)).     // total # of entries overall
            pack("V", strlen($ctrldir)).             // size of central dir
            pack("V", strlen($data)).                 // offset to start of central dir
            "\x00\x00";                             // .zip file comment length
    }
}

include("plog-globals.php");


if (!isset($_REQUEST["checked"]) || (!is_array($_REQUEST["checked"]))){
	echo 'No pictures were selected.';
}
else{
	create_zip($_REQUEST["checked"], $_REQUEST["dl_type"]);
}

function create_zip($checked, $level){
global $zipfile;
	
	$dir = "Plogger.".date("Y.m.d")."/";
	
	$zipfile = new zipfile();
	// add the subdirectory ... important!
	// $zipfile -> add_dir($dir);

	add_photos($checked, $level, $dir, $zipfile);  
	  
	// the next three lines force an immediate download of the zip file:
	header("Content-type: application/octet-stream");   
	header("Content-disposition: attachment; filename=plog-package-".date("Y.m.d").".zip");   
	echo $zipfile -> file();  
	
	return;
}

function add_photos($checked, $type, $dir){
	global $TABLE_PREFIX;
	global $zipfile;
	
	if ($type == "collections"){
		foreach ($checked as $cid){
			$query = "SELECT * FROM `".$TABLE_PREFIX."collections` WHERE `id`='".$cid."'";
			$result = run_query($query);
			
			while ($row = mysql_fetch_assoc($result)){
				$query = "SELECT * FROM `".$TABLE_PREFIX."albums` WHERE `parent_id`='".$row["id"]."'";
				$newresult = run_query($query);
				
				$newchecked = array();
				
				while ($newrow = mysql_fetch_assoc($newresult)){
					$newchecked[] = $newrow["id"];
				}
				
				$newdir = $row["name"];
				
				$i = 1;
				
				while (is_dir($newdir)){
					$newdir = $row["name"] . " (".$i++.")";
				}
				
				// $zipfile -> add_dir($dir . $newdir);
				
				add_photos($newchecked, "albums", $dir . $newdir . "/");
			}
		}
	}
	elseif($type == "albums"){
		foreach ($checked as $aid){
			$query = "SELECT * FROM `".$TABLE_PREFIX."albums` WHERE `id`='".$aid."'";
			$result = run_query($query);
			
			while ($row = mysql_fetch_assoc($result)){
				$query = "SELECT * FROM `".$TABLE_PREFIX."pictures` WHERE `parent_album`='".$row["id"]."'";
				$newresult = run_query($query);
				
				$newchecked = array();
				
				while ($newrow = mysql_fetch_assoc($newresult)){
					$newchecked[] = $newrow["id"];
				}
				
				$newdir = $row["name"];
				
				$i = 1;
				
				while (is_dir($newdir)){
					$newdir = $row["name"] . " (".$i++.")";
				}
				
				
				// $zipfile -> add_dir($dir . $newdir);
				
				add_photos($newchecked, "pictures", $dir . $newdir . "/");
			}
		}
	}
	elseif($type == "pictures"){
		foreach ($checked as $pid){
			$query = "SELECT * FROM `".$TABLE_PREFIX."pictures` WHERE `id`='".$pid."'";
			$result = run_query($query);
			
			while ($row = mysql_fetch_assoc($result)){
				$file_contents = file_get_contents("images/".$row["path"], true);
				$zipfile -> add_file($file_contents, $row["path"]);

			}
		}
	}
	
	return;
}

?>